import Joi from 'joi';
import { path } from 'ramda';
import debugCheck from '@kuiper-helpers/debug-check';
import * as validation from '../../common/validation';
import joiOmit from '../helpers/joiOmit';
import errorCodesBuilder from '../helpers/errorCodesBuilder';
import findManyFilter from '../../common/validation/findManyFilter';

const errorCodes = errorCodesBuilder();

export const pagination = {
	tags: ['api', 'task'],
	description: '任务列表-分页查看',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		payload: Joi.object({
			page: Joi.number().default(1).description('当前页'),
			perPage: Joi.number().default(10).description('每页条目数'),
			filter: findManyFilter.task.$_terms.keys
				.reduce((obj, { key, schema }) => {
					if (key === 'uid') {
						return obj.append({ uid: Joi.string().allow(null) });
					}
					if (key === 'OR') {
						return obj.append({
							OR: Joi.array().items(
								schema.$_terms.items[0].$_terms.keys.reduce(
									(obj, { key, schema }) => {
										if (key !== 'uid') return obj.append({ [key]: schema });
										return obj.append({ uid: Joi.string().allow(null) });
									},
									Joi.object()
								)
							),
						});
					}
					return obj.append({ [key]: schema });
				}, Joi.object())
				.append({
					targetSearch: Joi.string().description('正则过滤target'),
					statusIn: Joi.array().items(Joi.string()).description('任务状态'),
					dateRange: Joi.object({
						startTime: Joi.date().description('开始时间。大于等于'),
						endTime: Joi.date().description('结束时间。小于等于'),
					}).description('结束时间段过滤'),
					startTimeGTE: Joi.date().description('开始时间。大于等于'),
					startTimeLTE: Joi.date().description('开始时间。小于等于'),
					endTimeGTE: Joi.date().description('结束时间。大于等于'),
					endTimeLTE: Joi.date().description('结束时间。小于等于'),
					_operators: Joi.object().unknown(),
				}),
		}),
	},

	// response: {
	// 	schema: Joi.object({
	// 		data: Joi.object({
	// 			TaskPagination: Joi.object({
	// 				count: Joi.number().description('总条数'),
	// 				pageInfo: Joi.object({
	// 					currentPage: Joi.number().description('当前页数'),
	// 					perPage: Joi.number().description('每页条数'),
	// 					pageCount: Joi.number().description('总页数'),
	// 					itemCount: Joi.number().description('总条数'),
	// 					hasNextPage: Joi.boolean().description('是否有下一页'),
	// 					hasPreviousPage: Joi.boolean().description('是否有上一页'),
	// 				}),
	// 				items: Joi.array().items(
	// 					validation.taskWithId.append({
	// 						user: Joi.object({
	// 							username: Joi.string().description('用户名'),
	// 						}),
	// 						job: joiOmit(validation.jobWithId).allow(null),
	// 						asset: joiOmit(validation.assetWithId).allow(null),
	// 					})
	// 				),
	// 			}),
	// 		}),
	// 	}).label('Response'),
	// },

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					payload: { page, perPage, filter },
				} = request;

				return JSON.stringify({
					variables: {
						page,
						perPage,
						filter,
					},
					// #region query
					query: `
						query($page: Int = 1, $perPage: Int = 10, $filter: FilterFindManyTaskInput, $sort: SortFindManyTaskInput = _ID_DESC) {
							TaskPagination(page: $page, perPage: $perPage, filter: $filter, sort: $sort) {
								count
								pageInfo {
									currentPage
									perPage
									pageCount
									itemCount
									hasNextPage
									hasPreviousPage
								}
								items {
									_id
									sourceIp
									uid
									taskId
									taskIdx
									prevTaskId
									refType
									refId
									isSpecialTask
									domain
									target
									taskType
									securityStatus
									startTime
									endTime
									status
									progress
									exception
									triggerType
									nextExecDate
									isLatestTask
									repeat {
										cron
										tz
										startTime
										endTime
										limit
										every
										count
									}
									result {
										warningCount
										warningResolvedCount
										warningUnresolvedCount
										computedStats
										stats {
											subdomainCount
											ipCount
											portCount
											ipBindDomainCount
											addSubdomainCount
											addIpCount
											addPortCount
											addIpBindDomainCount
											removeSubdomainCount
											removeIpCount
											removePortCount
											removeIpBindDomainCount
											changePortServiceCount
											url
											keyword
											keyword1
											keyword2
											keyword3
											keyword4
											keyword5
											keyword6
											keyword7
											keyword8
											privacy_disclosure
											privacy_disclosure1
											privacy_disclosure2
											privacy_disclosure3
											privacy_disclosure4
										}
									}
									alertSettings{
										alertGroupIds
										notification{
											email
											sms
											wechat
											inBox
										}
									}
									taskSettings {
										enable
										name
										sourceIp
										target
										collect
										alert
										interval
									}
									user {
										username
									}
									job {
										_id
										note
										assetId
										enableMonitor
										enableAlert
										securityEventSettings{
											enable
										}
										contentSettings{
											enable
										}
										vulSettings{
											enable
										}
										sslSettings{
											enable
										}
										httpSettings{
											enable
										}
										pingSettings{
											enable
										}
									}
									asset {
										_id
										taskSettings {
											enable
											name
											sourceIp
											target
											collect
											alert
											interval
										}
									}
								}
							}
						}`,
					// #endregion
				});
			},
			onResponse(result, request) {
				const securityStatus = path(
					[
						'payload',
						'filter',
						'result',
						'addition',
						'detail',
						'securityStatus',
					],
					request
				);

				if (securityStatus) {
					// 按状态过滤 detail 列表中的节点
					// eslint-disable-next-line no-unused-expressions
					result?.data?.TaskPagination?.items?.forEach(item => {
						const detail = item.result?.addition.detail;
						if (!detail && detail.length) return;
						item.result.addition.detail = detail.filter(
							x => x.securityStatus === securityStatus
						);
					});
				}

				return result;
			},
		},
	},
};

export const findMany = {
	tags: ['api', 'task'],
	description: '监测任务列表',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		payload: findManyFilter.task.keys({
			_operators: Joi.object().unknown(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskMany: Joi.array().items(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const { payload } = request;

				return JSON.stringify({
					variables: { filter: payload },
					// #region query
					query: `
						query($filter: FilterFindManyTaskInput) {
							TaskMany(filter: $filter, limit: 0) {
								_id
								sourceIp
								uid
								taskId
								prevTaskId
								refType
								refId
								isSpecialTask
								domain
								target
								taskType
								securityStatus
								startTime
								endTime
								status
								progress
								exception
								triggerType
								nextExecDate
								isLatestTask
								repeat {
									cron
									tz
									startTime
									endTime
									limit
									every
									count
								}
								result {
									warningCount
									warningResolvedCount
									warningUnresolvedCount
									warnings {
										id
										title
										description
										impact
										category
										affects
										level
										isResolved
										ignoredTime
									}
								}
								taskSettings {
									enable
									name
									sourceIp
									target
									collect
									alert
									interval
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const findById = {
	tags: ['api', 'task'],
	description: '根据ID查询监测任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string(),
		}),
	},

	// response: {
	// 	schema: Joi.object({
	// 		data: Joi.object({
	// 			TaskById: validation.taskWithId.append({
	// 				user: Joi.object({
	// 					_id: Joi.string(),
	// 					username: Joi.string().description('用户名'),
	// 				}),
	// 			}),
	// 		}),
	// 	}).label('Response'),
	// },

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
				} = request;

				return JSON.stringify({
					variables: { _id: taskId },
					// #region query
					query: `
						query($_id: MongoID!) {
							TaskById: TaskOne(filter: { _id: $_id }) {
								_id
								sourceIp
								uid
								taskId
								prevTaskId
								refType
								refId
								jobId
								job {
									note
									_id
                  cydEnabled
								}
								isSpecialTask
								domain
								target
								taskType
								securityStatus
								startTime
								endTime
								status
								progress
								exception
								triggerType
								nextExecDate
								isLatestTask
								repeat {
									cron
									tz
									startTime
									endTime
									limit
									every
									count
								}
								result {
									warnings {
										_id
										id
										title
										description
										impact
										level
										category
										affects
										detail
										isResolved
										ignoredTime
									}
									addition
									stats {
										subdomainCount
										ipCount
										portCount
										ipBindDomainCount
									}
									ipPorts {
										ip
										hostname
										location
										ports {
											port
											service
											proto
											server
											version
										}
									}
									subDomains {
										host
										point
									}
									ipBindDomains {
										ip
										domains {
											domain
											title
										}
									}
								}
								taskSettings {
									enable
									name
									sourceIp
									target
									collect
									alert
									interval
								}
								user {
									_id
									username
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const count = {
	tags: ['api', 'task'],
	description: '监测任务数量统计',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		payload: Joi.object({
			filter: findManyFilter.task.keys({
				startTimeGTE: Joi.date().description('开始时间。大于等于'),
				startTimeLTE: Joi.date().description('开始时间。小于等于'),
				endTimeGTE: Joi.date().description('结束时间。大于等于'),
				endTimeLTE: Joi.date().description('结束时间。小于等于'),
				_operators: Joi.object().unknown(),
			}),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskCount: Joi.number().description('数量'),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					payload: { filter },
				} = request;

				return JSON.stringify({
					variables: { filter },
					// #region query
					query: `
						query($filter: FilterCountTaskInput) {
							TaskCount(filter: $filter)
						}`,
					// #endregion
				});
			},
		},
	},
};

export const removeById = {
	tags: ['api', 'task'],
	description: '删除任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskRemoveById: Joi.object({
					numAffected: Joi.number(),
				}),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
				} = request;

				return JSON.stringify({
					variables: { taskId },
					// #region query
					query: `
						mutation($taskId: MongoID!) {
							TaskRemoveById: TaskRemoveMany(filter: { _ids: [$taskId] }) {
								numAffected
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const removeMany = {
	tags: ['api', 'task'],
	description: '删除任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		payload: Joi.array().items(Joi.string()).required(),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskRemoveMany: Joi.object({
					numAffected: Joi.number(),
				}),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const { payload } = request;

				return JSON.stringify({
					variables: { _ids: payload },
					// #region query
					query: `
						mutation($_ids: [MongoID]!) {
							TaskRemoveMany(filter: { _ids: $_ids }) {
								numAffected
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const markTaskWarnResolved = {
	tags: ['api', 'task'],
	description: '标记告警为已解决',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
		payload: Joi.object({
			warnIds: Joi.array().items(Joi.string()).description('告警ID').required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				markTaskWarnResolved: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
					payload: { warnIds },
				} = request;

				return JSON.stringify({
					variables: { taskId, warnIds },
					// #region query
					query: `
						mutation($taskId: MongoID!, $warnIds: [String]!) {
							markTaskWarnResolved: TaskWarnResolveState(taskId: $taskId, warnIds: $warnIds, isResolved: true) {
								_id
								result {
									warnings {
										id
										title
										level
										isResolved
										ignoredTime
									}
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const markTaskWarnUnresolved = {
	tags: ['api', 'task'],
	description: '标记告警为未解决',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
		payload: Joi.object({
			warnIds: Joi.array().items(Joi.string()).description('告警ID').required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskWarnResolveState: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
					payload: { warnIds },
				} = request;

				return JSON.stringify({
					variables: { taskId, warnIds },
					// #region query
					query: `
						mutation($taskId: MongoID!, $warnIds: [String]!) {
							TaskWarnResolveState(taskId: $taskId, warnIds: $warnIds, isResolved: false) {
								_id
								result {
									warnings {
										id
										title
										level
										isResolved
										ignoredTime
									}
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const changeWarnResolveState = {
	tags: ['api', 'task'],
	description: '修改告警状态',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
		payload: Joi.object({
			isResolved: Joi.boolean().description('告警状态').required(),
			warnIds: Joi.array().items(Joi.string()).description('告警ID').required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				TaskWarnResolveState: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
					payload: { warnIds, isResolved },
				} = request;

				return JSON.stringify({
					variables: { taskId, warnIds, isResolved },
					// #region query
					query: `
						mutation($taskId: MongoID!, $warnIds: [String]!, $isResolved: Boolean) {
							TaskWarnResolveState(taskId: $taskId, warnIds: $warnIds, isResolved: $isResolved) {
								_id
								result {
									warnings {
										id
										title
										level
										isResolved
										ignoredTime
									}
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const ignoreTaskWarn = {
	tags: ['api', 'task'],
	description: '忽略告警',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
		payload: Joi.object({
			warnIds: Joi.array().items(Joi.string()).description('告警ID').required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				ignoreWarn: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
					payload: { warnIds },
				} = request;

				return JSON.stringify({
					variables: { taskId, warnIds },
					// #region query
					query: `
						mutation($taskId: MongoID!, $warnIds: [String]!) {
							ignoreWarn(taskId: $taskId, warnIds: $warnIds) {
								_id
								result {
									warnings {
										id
										title
										level
										ignoredTime
										isResolved
									}
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const unignoreTaskWarn = {
	tags: ['api', 'task'],
	description: '取消忽略告警',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
		payload: Joi.object({
			warnIds: Joi.array().items(Joi.string()).description('告警ID').required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				unignoreWarn: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
					payload: { warnIds },
				} = request;

				return JSON.stringify({
					variables: { taskId, warnIds },
					// #region query
					query: `
						mutation($taskId: MongoID!, $warnIds: [String]!) {
							unignoreWarn(taskId: $taskId, warnIds: $warnIds) {
								_id
								result {
									warnings {
										id
										title
										level
										ignoredTime
										isResolved
									}
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const stop = {
	tags: ['api', 'task'],
	description: '停止监测任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
				} = request;
				request.log.debug({ taskId }, '停止监测任务');

				return JSON.stringify({
					variables: { taskId },
					// #region query
					query: `
						mutation($taskId: MongoID!) {
							stopTask(taskId: $taskId) {
								_id
								sourceIp
								uid
								taskId
								prevTaskId
								refType
								refId
								isSpecialTask
								domain
								target
								taskType
								securityStatus
								startTime
								endTime
								status
								progress
								exception
								triggerType
								nextExecDate
								isLatestTask
								repeat {
									cron
									tz
									startTime
									endTime
									limit
									every
									count
								}
								taskSettings {
									enable
									name
									sourceIp
									target
									collect
									alert
									interval
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const retry = {
	tags: ['api', 'task'],
	description: '重新执行监测任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}),
	},

	response: {
		schema: Joi.object({
			data: Joi.object({
				retryTask: joiOmit(validation.taskWithId),
			}),
		}).label('Response'),
	},

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const {
					params: { taskId },
				} = request;
				request.log.debug({ taskId }, '重新执行监测任务');

				return JSON.stringify({
					variables: { taskId },
					// #region query
					query: `
						mutation($taskId: MongoID!) {
							retryTask(taskId: $taskId) {
								_id
								sourceIp
								uid
								taskId
								prevTaskId
								refType
								refId
								isSpecialTask
								domain
								target
								taskType
								securityStatus
								startTime
								endTime
								status
								progress
								exception
								triggerType
								nextExecDate
								isLatestTask
								repeat {
									cron
									tz
									startTime
									endTime
									limit
									every
									count
								}
								taskSettings {
									enable
									name
									sourceIp
									target
									collect
									alert
									interval
								}
							}
						}`,
					// #endregion
				});
			},
		},
	},
};

export const manualTask = {
	tags: ['api', 'task'],
	description: '自定义监测任务',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	handler: {
		injectGraphql: {
			payloadBuilder(request) {
				const { payload } = request;
				request.log.debug(payload, '自定义监测任务');

				if (payload.needAlert !== undefined) {
					payload.alert.enable = payload.needAlert;
					delete payload.needAlert;
				}
				const enable = payload.alertSettings.enable;
				return JSON.stringify({
					variables: payload,
					// #region query
					query: `
						mutation(
							$uid: MongoID,
							$targetId: MongoID
							$isSpecialTask: Boolean
							$vulcollect: JSON
							$sslcollect: JSON
							$securityEventcollect: JSON
							$assetcollect: JSON
							$contentcollect: JSON
							$alert: JSON
							$alertSettings: JSON
							$prelogin: JSON
							$customMonitorPage: UpdateOneJobCustomMonitorPageInput
						) {
							vul: manualTask(
								uid:$uid
								enable:${enable.vul}
								targetId: $targetId
								taskType: "vul"
								isSpecialTask: $isSpecialTask
								collect: $vulcollect
								alert: $alert
								alertSettings:$alertSettings
								prelogin: $prelogin
								customMonitorPage: $customMonitorPage
							)
							ssl: manualTask(
								uid:$uid
								enable:${enable.ssl}
								targetId: $targetId
								taskType: "ssl"
								isSpecialTask: $isSpecialTask
								collect: $sslcollect
								alert: $alert
								alertSettings:$alertSettings
								prelogin: $prelogin
								customMonitorPage: $customMonitorPage
							)
							securityEvent: manualTask(
								uid:$uid
								enable:${enable.securityEvent}
								targetId: $targetId
								taskType: "securityEvent"
								isSpecialTask: $isSpecialTask
								collect: $securityEventcollect
								alert: $alert
								alertSettings:$alertSettings
								prelogin: $prelogin
								customMonitorPage: $customMonitorPage
							)
							asset: manualTask(
								uid:$uid
								enable:${enable.asset}
								taskType: "asset"
								targetId: $targetId
								collect: $assetcollect
								alert: $alert
								alertSettings:$alertSettings
								prelogin: $prelogin
								customMonitorPage: $customMonitorPage
							)
							content: manualTask(
								uid: $uid
								enable: ${enable.content}
								targetId: $targetId
								taskType: "content"
								isSpecialTask: $isSpecialTask
								collect: $contentcollect
								alert: $alert
								alertSettings: $alertSettings
								prelogin: $prelogin
								customMonitorPage: $customMonitorPage
							)
						}`,
					// #endregion
				});
			},
		},
	},
};

export const monitorTaskUpdate = {
	tags: ['api', 'task'],
	description: '监测任务回调',
	auth: debugCheck('disable-open-api-auth')
		? false
		: {
				mode: 'required',
				access: {
					// 只允许使用 URL Token 访问
					entity: 'app',
				},
		  },

	validate: {
		params: Joi.object({
			taskId: Joi.string().required(),
		}).unknown(),
		payload: Joi.object({
			taskId: Joi.string().description('任务ID').required(),
			crontabId: Joi.string().description('定时任务ID'),
			status: Joi.string()
				.valid('waiting', 'active', 'failed', 'completed')
				.required()
				.description('任务状态'),
			progress: Joi.number().description('任务进度'),
			data: Joi.object().unknown().description('任务结果'),
			time: Joi.date().description('触发时间'),
			code: Joi.string().description('任务失败错误代码'),
			message: Joi.string().description('任务消息'),
		}),
	},

	response: {
		schema: Joi.object({
			message: Joi.string(),
		}).label('Response'),
	},

	async handler(request) {
		const {
			payload: {
				taskId,
				crontabId,
				status,
				progress,
				data,
				time,
				code,
				message,
			},
			server: {
				app: {
					model: { Taskv2 },
				},
			},
		} = request;

		request.log.info(
			{ taskId, crontabId, code, progress, status },
			'监测任务回调'
		);

		const record = {
			taskId,
			crontabId,
			status,
			progress,
			result: { addition: data },
			time,
			code,
			message,
		};

		switch (status) {
			case 'waiting':
			case 'active':
				record.startTime = time;
				break;
			case 'failed':
			case 'completed':
				record.endTime = time;
				break;
		}

		try {
			await Taskv2.updateOne({ taskId }, record, { upsert: true });
		} catch (err) {
			const error = errorCodes['[01]监测任务状态回调更新失败'].from(err);
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		return { message: '更新成功' };
	},
};
